﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
using Microsoft.Synchronization.Data;
using System.Data.SqlClient;
using System.Data;

namespace SyncLib.Data
{
    public class KDataBatchFactory
    {
        public static KDataBatch Deserialize(string batchFileName)
        {
            return Deserialize(batchFileName, true);
        }

        public static KDataBatch Deserialize(string batchFileName, bool deserializeData)
        {
            KDataBatch info2;
            BinaryFormatter formatter = new BinaryFormatter();
            // formatter.Binder = new KpSyncBatchSerializationBinder();
            FileStream serializationStream = new FileStream(batchFileName, FileMode.Open);
            try
            {
                KDataBatch info = (KDataBatch)formatter.Deserialize(serializationStream);
                if (deserializeData)
                {
                    info.DataSetSurrogate = (DataSetSurrogate)formatter.Deserialize(serializationStream);
                }
                info2 = info;
            }
            finally
            {
                serializationStream.Close();
            }
            return info2;
        }

        public static void Serialize(KDataBatch batchInfo, string batchFileName)
        {
            
            BinaryFormatter formatter = new BinaryFormatter();
            FileStream serializationStream = new FileStream(batchFileName, FileMode.Create);
            try
            {
                formatter.Serialize(serializationStream, batchInfo);
                formatter.Serialize(serializationStream, batchInfo.DataSetSurrogate);
                serializationStream.Flush();
            }
            finally
            {
                serializationStream.Close();
            }
        }
        public static void SerializeToSql(KDataBatch batchInfo, SqlConnection connection, SqlTransaction transaction, Guid clientId, string location)
        {
            using (SqlCommand cmd = new SqlCommand("InsertSyncDataBatch", connection, transaction))
            {
                cmd.CommandType = CommandType.StoredProcedure;
                cmd.Parameters.Add("@ClientId", SqlDbType.UniqueIdentifier).Value = clientId;
                cmd.Parameters.Add("@Location", SqlDbType.VarChar, 32).Value = location;
                cmd.Parameters.Add("@BatchKey", SqlDbType.NVarChar, 512).Value = batchInfo.FileName;
                byte[] contents = KDataBatchFactory.GetBytes(batchInfo);
                cmd.Parameters.Add("@BatchContent", SqlDbType.Image).Value = contents;
                cmd.Parameters.Add("@ContentLength", SqlDbType.Int).Value = contents.Length;
                cmd.ExecuteNonQuery();
            }
        }
        public static KDataBatch DeserializeFromSql(string batchFileName, SqlConnection connection, SqlTransaction transaction, Guid clientId, string location)
        {
            using (SqlCommand cmd = new SqlCommand("SelectSyncDataBatch", connection, transaction))
            {
                cmd.CommandType = CommandType.StoredProcedure;
                cmd.Parameters.Add("@ClientId", SqlDbType.UniqueIdentifier).Value = clientId;
                cmd.Parameters.Add("@Location", SqlDbType.VarChar, 32).Value = location;
                cmd.Parameters.Add("@BatchKey", SqlDbType.NVarChar, 512).Value = batchFileName;
                using (SqlDataReader reader = cmd.ExecuteReader())
                {
                    if (reader.Read())
                    {
                        int contentLength = reader.GetInt32(4);
                        byte[] contents=new byte[contentLength];
                        reader.GetBytes(3, 0, contents, 0, contentLength);
                        using (MemoryStream ms = new MemoryStream(contents))
                        {
                            ms.Position = 0;
                            BinaryFormatter formatter = new BinaryFormatter();
                            KDataBatch batch= (KDataBatch)formatter.Deserialize(ms);
                            return batch;
                        }
                    }
                }

            }
            return null;
        }
        public static byte[] GetBytes(KDataBatch batchInfo)
        {

            BinaryFormatter formatter = new BinaryFormatter();
            MemoryStream serializationStream = new MemoryStream();
            try
            {
                batchInfo.FileName = "";
                formatter.Serialize(serializationStream, batchInfo);
                //formatter.Serialize(serializationStream, batchInfo.DataSetSurrogate);
                serializationStream.Flush();
                serializationStream.Position = 0;
                byte[] contents= new byte[serializationStream.Length];
                int offset=0;
                int length=(int)serializationStream.Length;

                while (serializationStream.Position < serializationStream.Length)
                {
                    serializationStream.Read(contents, offset, length);
                    offset = length;
                    length = (int)(serializationStream.Length - offset);
                }
                return contents;
            }
            finally
            {
                serializationStream.Close();
                serializationStream.Dispose();
            }
        }
    }
}
